/*
 * CGlobalLog.cpp
 *
 *  Created on: Oct 24, 2011
 *      Author: fferri
 */

#include "GlobalLog.h"
#include <iostream>
#include <cstdio>

namespace glog {

void CGlobalLog::DEBUG_MSG(const std::string& appender,const char* msg, ...)
{
	va_list argptr;
    va_start(argptr,msg);
	addMessage_(appender, LOGLEVEL_DEBUG, msg, argptr);
	va_end(argptr);
}
void CGlobalLog::INFO_MSG(const std::string& appender,const char* msg, ...){
	   va_list argptr;
	   va_start(argptr,msg);
	   addMessage_(appender, LOGLEVEL_INFO, msg, argptr);
	   va_end(argptr);
}
void CGlobalLog::WARNING_MSG(const std::string& appender, const char* msg, ...){
	   va_list argptr;
	   va_start(argptr,msg);
	   addMessage_(appender, LOGLEVEL_WARNING, msg, argptr);
	   va_end(argptr);
}
void CGlobalLog::ERROR_MSG(const std::string& appender, const char* msg, ...){
	   va_list argptr;
	   va_start(argptr,msg);
	   addMessage_(appender, LOGLEVEL_ERROR, msg, argptr);
	   va_end(argptr);
	   //this->processMessages();
}
void CGlobalLog::FATAL_MSG(const std::string& appender, const char* msg, ...){
	   va_list argptr;
	   va_start(argptr,msg);
	   addMessage_(appender, LOGLEVEL_FATAL, msg, argptr);
	   va_end(argptr);
	   //this->processMessages();
}

void CGlobalLog::addMessage_(const std::string& appender, LogLevel level,const char* msg, va_list args )
{

	//va_list args;
	char buffer[1000];
	vsprintf( buffer, msg, args ); // Note: vsprintf is deprecated; consider using vsprintf_s instead
	addMessage(appender,level, std::string(buffer));
}

void CGlobalLog::processMessages()
{
	// recorro todos los appenders y para cada uno, los mensajes asociada
	t_appenderQueueMap::iterator it = m_msgQueue.begin();
	for(; it != m_msgQueue.end(); ++it)
	{
		//std::cout << "Procesando appender " << (*it).first << "\n";

		// Comprobando si tiene listeners asociados. Si no tiene, vaciar esa cola. Si los tiene, para cada listener, llamar a writeToLog
		// y mandarle los mensajes.
		t_appenderToListenerListMap::iterator listeners =  m_suscriptionMap.find((*it).first);
		if(listeners == m_suscriptionMap.end())
		{
			//std::cout << "El appender " << (*it).first << " no tiene listeners asociados. Vaciando colas...\n";
			while(!(*it).second.empty())
			{
				CStoredMessage* m = (*it).second.front();
				delete m;
				(*it).second.pop();
			}
		}
		else
		{
			// Recorremos uno por uno cada mensaje y lo enviamos a cada uno de los listeners
			while(!(*it).second.empty()) // mientras la lista de mensajes no quede vacia
			{

				std::list<boost::shared_ptr<IListener> >::iterator ll = (*listeners).second.begin();
				CStoredMessage* msg = (*it).second.front();
				for(; ll != (*listeners).second.end(); ++ll)
				{
					(*ll)->writeToLog(msg->m_appender,msg->logLevel, msg->msgTime, msg->message);
				}
				delete msg;
				(*it).second.pop();  // eliminar el mensaje
			}
		}
	}
}
void CGlobalLog::addAppender(const std::string& app)
{
	m_msgQueue[app];
}
void CGlobalLog::addListener(boost::shared_ptr<IListener> l, const std::string& appender)
{
	m_suscriptionMap[appender].push_back(l);
}
std::list<std::string> CGlobalLog::getAppenderList() const
{
	t_appenderQueueMap::const_iterator it = m_msgQueue.begin();
	std::list<std::string> appenders;

	for(; it != m_msgQueue.end(); ++it )
	{
		appenders.push_back((*it).first);
	}
	return appenders;
}
void CGlobalLog::addMessage(const std::string& appender, LogLevel lvl, const std::string& message)
{
	// Registrar mensajes cuyo nivel es igual o mayor que el minimo nivel seteaddo en setMinimumLevel
	if(lvl >= m_minimumLevel)
		m_msgQueue[appender].push(new CStoredMessage(appender, lvl, message));

}
LogLevel CGlobalLog::getMinimunLevel() const
{
	return m_minimumLevel;
}

void CGlobalLog::setMiniumLevel(const LogLevel lvl)
{
	m_minimumLevel = lvl;
}

CGlobalLog::CGlobalLog():m_minimumLevel(LOGLEVEL_DEBUG) {
	// TODO Auto-generated constructor stub

}

CGlobalLog::~CGlobalLog() {

	// Esto hace que se escriban los mensajes y se limpien las colas.
	processMessages();
	//Borrar los listeners
	t_appenderToListenerListMap::iterator lstnrIter = m_suscriptionMap.begin();
	for(; lstnrIter != m_suscriptionMap.end(); ++lstnrIter)
	{
		t_ListenerList::iterator llIter =  (*lstnrIter).second.begin();
		llIter->reset();
	}
}

} /* namespace glog */
